#include "playback.h"
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <strings.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int FindStartCode (unsigned char *Buf, int zeros_in_startcode);
int getNextNal(FILE* inpf, unsigned char* Buf);

//playback addr port file

int main(int argc,char *argv[])
{
	int liSockfd;
	struct sockaddr_in laddrServer;
	unsigned char* lpustrBuf;
	FILE * lfdH264File; 
	int liNalLen;
	char lstrSendBuf[1500];
	RtpFixedHeader *lprtpheader;
	NaluHeader *lpnaluheader;
	FuHeader *lpfuheader;
	FuIndicator *lpfuindicator;
	unsigned short lusSeqNum =0;
	char *lpstrBufPos;
	
	char lstrAddr[20];
	int liPort;
	char lstrFileName[256];
		
	strcpy(lstrAddr,argv[1]);
	liPort=atoi(argv[2]);
	strcpy(lstrFileName,argv[3]);
	
	float lfFrameRate=15;
	unsigned int luiTimesTamp=0,luiTimesCurrent=0;
	luiTimesTamp=(unsigned int)(90000.0 / lfFrameRate); //+0.5);
	
	lpustrBuf = (unsigned char*)calloc ( 1000000, sizeof(char)); 

	
	/* init servaddr */
	bzero(&laddrServer, sizeof(laddrServer));
	laddrServer.sin_family = AF_INET;
	laddrServer.sin_port = htons(liPort);
	if(inet_pton(AF_INET, lstrAddr, &laddrServer.sin_addr) <= 0)
	{
		printf("[%s] is not a valid IPaddress\n",lstrAddr);
		exit(0);
	}

	liSockfd = socket(AF_INET, SOCK_DGRAM, 0);
	
	connect(liSockfd, (struct sockaddr *)&laddrServer, sizeof(laddrServer));
	
	lfdH264File = fopen(lstrFileName, "rb"); 
	
	while(!feof(lfdH264File)) 
	{
		usleep(1000*100);
		liNalLen = getNextNal(lfdH264File, lpustrBuf); 
		
		memset(lstrSendBuf,0,1500);//init send buffer
		
		lprtpheader =(RtpFixedHeader*)&lstrSendBuf[0]; 
		lprtpheader->ucPayload     = 96;  //h264
		lprtpheader->ucVersion     = 2;  //
		lprtpheader->ucMarker    = 0;   //
        lprtpheader->ulSsrc        = htonl(10);    //°
        
		if(liNalLen<=1400)
		{	
			//one package
			lprtpheader->ucMarker=1;
			lprtpheader->usSeqNo = htons(lusSeqNum ++); //
			//
			lpnaluheader =(NaluHeader*)&lstrSendBuf[12]; //
			lpnaluheader->ucF=(lpustrBuf[0]& 0x80)>>7;
			lpnaluheader->ucNri=(lpustrBuf[0]&0x60)>>5;//
			lpnaluheader->ucType=lpustrBuf[0]&0x1f;

			lpstrBufPos=&lstrSendBuf[13];//
			memcpy(lpstrBufPos,lpustrBuf+1,liNalLen-1);//
		
			luiTimesCurrent=luiTimesCurrent+luiTimesTamp;
			lprtpheader->ulTimestamp=htonl(luiTimesCurrent);
			send( liSockfd, lstrSendBuf, liNalLen+12, 0 );//·¢ËÍrtp°ü
			
			FILE *lfp;
			lfp=fopen("sendfile.264","ab+");
			fwrite(lstrSendBuf,liNalLen+12,1,lfp);
			fclose(lfp);
			
		}
		
		else if(liNalLen>1400)
		{
			int liPkgCount;
			int liLastPkgLen;
			liPkgCount=liNalLen/1400;//
			liLastPkgLen=liNalLen%1400;//
			int liTemp=0;
			luiTimesCurrent=luiTimesCurrent+luiTimesTamp;
			lprtpheader->ulTimestamp=htonl(luiTimesCurrent);
			while(liTemp<=liPkgCount)
			{
				lprtpheader->usSeqNo = htons(lusSeqNum ++); 
				if(!liTemp)
				{
					lprtpheader->ucMarker=0;
					lpfuindicator =(FuIndicator*)&lstrSendBuf[12]; 
					lpfuindicator->ucF=(lpustrBuf[0]& 0x80)>>7;
					lpfuindicator->ucNri=(lpustrBuf[0]&0x60)>>5;//
					lpfuindicator->ucType=28;
					
					lpfuheader =(FuHeader*)&lstrSendBuf[13];
					lpfuheader->ucE=0;
					lpfuheader->ucR=0;
					lpfuheader->ucS=1;
					lpfuheader->ucType=(lpustrBuf[0]) & 0x1f;
					
					lpstrBufPos=&lstrSendBuf[14];//
					memcpy(lpstrBufPos,lpustrBuf+1,1400);//

					send( liSockfd, lstrSendBuf, 1400+14, 0 );//
					liTemp++;
					
					FILE *lfp;
					lfp=fopen("sendfile.264","ab+");
					fwrite(lstrSendBuf, 1400+14,1,lfp);
					fclose(lfp);
				}
				//
				else if(liPkgCount==liTemp)//
				{
					//
					lprtpheader->ucMarker=1;
					//
					lpfuindicator =(FuIndicator*)&lstrSendBuf[12]; //
					lpfuindicator->ucF=(lpustrBuf[0]& 0x80)>>7;
					lpfuindicator->ucNri=(lpustrBuf[0]&0x60)>>5;//
					lpfuindicator->ucType=28;
						
					//
					lpfuheader =(FuHeader*)&lstrSendBuf[13];
					lpfuheader->ucR=0;
					lpfuheader->ucS=0;
					lpfuheader->ucE=1;
					lpfuheader->ucType=lpustrBuf[0] & 0x1f;
					
					//
					lpstrBufPos=&lstrSendBuf[14];//
					memcpy(lpstrBufPos,lpustrBuf+liTemp*1400+1,liLastPkgLen-1);//
					send( liSockfd, lstrSendBuf, liLastPkgLen-1+14, 0 );//
					liTemp++;
					
					FILE *lfp;
					lfp=fopen("sendfile.264","ab+");
					fwrite(lstrSendBuf, liLastPkgLen-1+14,1,lfp);
					fclose(lfp);

				}
				else if(liTemp<liPkgCount&&0!=liTemp)
				{
					//
					lprtpheader->ucMarker=0;
					
					lpfuindicator =(FuIndicator*)&lstrSendBuf[12]; //
					lpfuindicator->ucF=(lpustrBuf[0]& 0x80)>>7;
					lpfuindicator->ucNri=(lpustrBuf[0]&0x60)>>5;//
					lpfuindicator->ucType=28;
						
					//
					lpfuheader =(FuHeader*)&lstrSendBuf[13];
					//lpfuheader->E=0;
					lpfuheader->ucR=0;
					lpfuheader->ucS=0;
					lpfuheader->ucE=0;
					lpfuheader->ucType=lpustrBuf[0] & 0x1f;
				
					lpstrBufPos=&lstrSendBuf[14];//
					memcpy(lpstrBufPos,lpustrBuf+liTemp*1400+1,1400);//				
					send( liSockfd, lstrSendBuf, 1400+14, 0 );//
					liTemp++;
					
					FILE *lfp;
					lfp=fopen("sendfile.264","ab+");
					fwrite(lstrSendBuf, 1400+14,1,lfp);
					fclose(lfp);
				}
			}
		}
	}
	
	close(liSockfd);
	fclose(lfdH264File);
	

	return 0;
}



int FindStartCode (unsigned char *Buf, int zeros_in_startcode)
{
  int info;
  int i;

  info = 1;
  for (i = 0; i < zeros_in_startcode; i++)
    if(Buf[i] != 0)
      info = 0;

  if(Buf[i] != 1)
    info = 0;
  return info;
}

int getNextNal(FILE* inpf, unsigned char* Buf)
{
	int pos = 0;
	int StartCodeFound = 0;
	int info2 = 0;
	int info3 = 0;

	while(!feof(inpf) && (Buf[pos++]=fgetc(inpf))==0);

	//ignore head
	pos=0;

	while (!StartCodeFound)
	{
		if (feof (inpf))
		{
//			return -1;
			return pos-1;
		}
		Buf[pos++] = fgetc (inpf);
		info3 = FindStartCode(&Buf[pos-4], 3);
		if(info3 != 1)
			info2 = FindStartCode(&Buf[pos-3], 2);
		StartCodeFound = (info2 == 1 || info3 == 1);
	}
	if(info3)
	{
		fseek (inpf, -4, SEEK_CUR);
		return pos-4;
	}
	else
	{
		fseek (inpf, -3, SEEK_CUR);
		return pos-3;
	}
	
	return -1;
}
